Function.RegisterNamespace("System.EnvironmentStrategy");

System.EnvironmentStrategy.Wscript=function(){
    // Private members
    var _outputFileName="WScript_CommandOutput.tmp";
    var _useStdIo=true;

    // IEnvironmentStrategy members
    this.Execute=function(command,parameters,voidOutput){
        try{
            var fullCommand=[command].concat(parameters||[]).join(' ');
            var shell=WScript.CreateObject("WScript.Shell");
            var exitCode=shell.Run(voidOutput?fullCommand:[fullCommand,">",_outputFileName].join(' '),0,true);
            if(exitCode!=0)throw new Error(String.Format("Command '{0}' exited with code {1}.",fullCommand,exitCode));            
            if(!voidOutput)return System.IO.File.Strategies.Get(Object.Global()).GetFile(_outputFileName);
        }catch(e){
            throw e;
        }finally{
            System.IO.File.DeleteFile(_outputFileName);
        }
    };

    this.Exit=function(errorCode){
        WScript.Quit(errorCode);
    };


    this.GetNewLine=function(){
        return "\r\n";
    };
    
    this.GetParameters=function(){
        var args={
            named:{},
            unnamed:[]
        };
        var params=WScript.Arguments;
        for(var i=0;i<params.length;i++){
            var param=String.Trim(params(i));
            if(String.StartsWith(param,'/')&&String.Contains(param,':')){
                param=String.TrimStart(param,'/').split(':');
                args.named[param[0].toLowerCase()]=param.slice(1).join(':');
            }else args.unnamed.push(param);
        }
        return args;
    };
    
    this.GetWorkingDirectory=function(){
        return System.IO.Path.Normalize(WScript.CreateObject("WScript.Shell").CurrentDirectory);
    };

    this.Write=function(message1,message2,messageN){
        Array.ForEach(Array.prototype.slice.call(arguments,0),writeHandlerPredicate(WScript.StdOut));
    };
    
    this.WriteError=function(message1,message2,messageN){
        Array.ForEach(Array.prototype.slice.call(arguments,0),writeHandlerPredicate(WScript.StdErr));
    };
    
    // IStrategySpecification members
    this.IsSatisfiedBy=function(candidate){
        return typeof(WScript)!="undefined";
    };
    
    //Private methods
    function writeHandlerPredicate(pipe){
        return function(message,context){
            if(_useStdIo){
                try{
                    pipe.Write(message);
                    return;
                }catch(e){
                    _useStdIo=false;
                }
            }
            WScript.Echo(message);
        }
    }
    
};

System.EnvironmentStrategy.Wscript.Implement(System.EnvironmentStrategy.IEnvironmentStrategy,'System.EnvironmentStrategy.Wscript');
System.EnvironmentStrategy.Wscript.Implement(System.Script.Strategy.IStrategySpecification,'System.EnvironmentStrategy.Wscript');

System.Environment.Strategies.Add(System.EnvironmentStrategy.Wscript);